Skip to content

feat: choose share link type, add native uris - #2482

Merged
lidel merged 8 commits into
mainfrom
feat/share-modal-local-gateway-url
Jul 16, 2026
Merged

feat: choose share link type, add native uris#2482
lidel merged 8 commits into
mainfrom
feat/share-modal-local-gateway-url

Conversation

@lidel

@lidel lidel commented Mar 10, 2026

Copy link
Copy Markdown
Member

Problem

Share Link always built a URL on a third-party public gateway (dweb.link, with ipfs.io fallback) and Publish to IPNS hardcoded the public path gateway. There was no way to copy a native ipfs:// address, opt out of public gateways, or get a link pointing at your own node for other apps on the same machine (ipfs/ipfs-desktop#2500). The webui also probed gateways with image loads on startup and in Settings.

Fix

  • Settings gains a "Sharing IPFS Links" section used by both Share Link and Publish to IPNS: native ipfs:// addresses, local gateway links, or public gateway links (path or subdomain)
  • defaults are unchanged: ipfs.io and dweb.link stay prefilled and share links are built on dweb.link as before; flipping the default to native URIs is a follow-up where DEFAULT_SHARE_LINK_TYPE and the DEFAULT_*_GATEWAY constants are the only knobs
  • clearing a public gateway in Settings now opts out of it entirely; a link type whose gateway is missing falls back to a native address, so copied links are never empty or broken
  • Share modal offers a local HTTP link checkbox, with optional localhost subdomains for web apps that need origin isolation; links labeled local draw from the local gateway only, never a public fallback
  • gateway reachability probes removed; URL format is validated and the user's choice trusted

This is part of wider URI support to move away from copying public gateway links by default:

Demo

New "Sharing IPFS Links" section on the Settings screen:

2026-07-16_21-01

The Share modal looks the same as before, with a new opt-in checkbox for a local link:

1_2026-03-10_18-00

Once clicked, we update UI to indicate this is no longer for sharing with friends, and only other apps on the same machine. We use IP-based Path gateway that is known to work everywhere:

2_2026-03-10_18-00

Subdomain gateways do not work on all platforms, and only benefit web contexts (browser web apps, websites with relative paths etc), so are opt-in:

3_2026-03-10_18-00

allow copying local gateway links for use in external apps,
with optional localhost subdomain mode for web apps

- actions.js: doFilesShareLink returns local and subdomain links
- ShareModal: checkbox to toggle local link, nested checkbox for
  localhost subdomains, QR hidden in local mode
- Modals: passes new link variants to ShareModal
- en/files.json: added translation keys for new UI elements

@guillaumemichel guillaumemichel left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested & approved

lidel added 2 commits June 30, 2026 04:20
The share modal's local links flow through selectGatewayUrl, so the
Local Gateway URL override added in #2486 reaches them. Subdomain links
are offered only for domain gateways, since subdomain gateways cannot
resolve on a bare IP such as 127.0.0.1.

- files.js: add getLocalLinks, deriving both links from the gateway url
  (host, port, scheme); gate the subdomain link to domain hosts and to
  CIDs that fit a 63-char DNS label; share filename and base32 logic
  with getShareableLink
- actions.js: build the local links via getLocalLinks
- share-modal: clear the subdomain choice when the local link is
  unchecked, so it cannot silently reapply
- protocol.ts: type the share-link result as ShareLinks, not string
@lidel lidel added the status/blocked Unable to be worked further until needs are met label Jun 30, 2026
lidel added 2 commits June 30, 2026 22:36
Refine the local gateway share links so they resolve from other apps and
never leave the modal hanging when generation fails.

- files.js: a single loopback check in getLocalLinks drives both links,
  so the path link uses 127.0.0.1 (no DNS) and the subdomain link uses
  localhost (origins need a hostname); domain gateways and non-loopback
  IPs are left as-is
- modals: catch a failed link generation and show an error instead of a
  stuck "Generating..."
- en/files.json: add the error string; mark the plain link as HTTP
Share Link and Publish to IPNS copy native ipfs:// and ipns:// URIs
by default, with opt-in HTTP gateway links for cases that need them.

- add a Settings "Sharing IPFS Links" section to choose the link
  type: native, local path/subdomain, or public path/subdomain
- public gateways default to empty and are opt-in; a public option
  stays disabled until its URL is set, and clearing it reverts to
  native
- native URIs use canonical CIDv1: base32 for /ipfs, base36
  libp2p-key for /ipns; the same choice drives Publish to IPNS
- local links normalize loopback per type: 127.0.0.1 for path,
  localhost for subdomain
- remove online gateway reachability probes; previews, thumbnails,
  IPLD explorer and IPNS links load from the local gateway (override
  or Kubo config), never a third-party gateway unless configured
- consolidate the localhost to 127.0.0.1 subresource fix across
  previews, thumbnails, downloads, CAR links and pinning icons
- Explore links honor the configured gateways; a local gateway
  change refreshes previews at once and reloads the explorer on the
  next visit
@lidel

lidel commented Jul 1, 2026

Copy link
Copy Markdown
Member Author

Pushed some related tests / changes since review:

  • Share Link and Publish to IPNS now default to native ipfs://cid (and ipns://name). Public gateways are a conscious opt-in: nothing goes through ipfs.io or any other third party unless you configure a public gateway yourself.
  • Added a "Sharing IPFS Links" settings section to choose the link type, with e2e tests for the default and each option.

So the UI still makes sense the day ipfs.io and other public gateways go away:

This is part of wider URI support to move away from copying public gateways by default:

Preview of Settings page

Screenshot 2026-07-02 at 00-39-36 Settings IPFS

@lidel lidel changed the title feat: add local gateway URL options to share modal feat: choose share link type, native by default Jul 1, 2026
@lidel lidel removed the status/blocked Unable to be worked further until needs are met label Jul 1, 2026
@lidel
lidel marked this pull request as draft July 3, 2026 14:07
@lidel lidel added the status/blocked Unable to be worked further until needs are met label Jul 3, 2026
Share modal and content links labeled as local could point at the
public path gateway when the Kubo config exposed no usable gateway
address. Local links draw from the local gateway only (user override
or Kubo config), with related fixes and cleanups:

- loopback host rewrites apply to http only, so an https://localhost
  gateway keeps its certificate-valid hostname
- a link type without its gateway resolves to native before building,
  removing per-caller fallbacks in share and publish flows
- open-in-new-tab links (file preview, IPNS keys) honor the local
  subdomain choice from Settings for per-CID origin isolation
- pinning service icons resolve against the current gateway at read
  time and are omitted when no gateway is configured; previews and
  thumbnails skip gateway embeds in the same case
- shared toLoopbackIpUrl and GatewayForm replace per-site localhost
  rewrites and three near-identical gateway forms
- re-saving an unchanged Local Gateway URL no longer schedules an
  Explore page reload
@lidel lidel changed the title feat: choose share link type, native by default feat: choose share link type, add native uris Jul 16, 2026
lidel added 2 commits July 16, 2026 21:06
keep the defaults users already have (ipfs.io path gateway, dweb.link
subdomain gateway, share links on dweb.link) so this PR can merge
without changing any default behavior. defaulting to native ipfs://
sharing is left for a follow-up: DEFAULT_SHARE_LINK_TYPE and the
DEFAULT_*_GATEWAY constants are the only knobs to flip.

- a gateway cleared in Settings stays cleared across reloads; only a
  never-written setting gets the default
- selecting a public link type persists the gateway it points at, so an
  explicit opt-in keeps its gateway if the defaults change later
@lidel

lidel commented Jul 16, 2026

Copy link
Copy Markdown
Member Author

This PR no longer changes any defaults, so it can merge without touching existing behavior.

Changes since my last update:

  • c33c8a7 keeps today's defaults: ipfs.io path and dweb.link subdomain gateways prefilled, share links built on dweb.link as before. Native-by-default moves to a follow-up PR; DEFAULT_SHARE_LINK_TYPE and the DEFAULT_*_GATEWAY constants are the only knobs to flip.
  • Opting out still works: a gateway cleared in Settings stays cleared, and links fall back to native addresses.
  • Picking a public link type persists the gateway it points at, so an explicit choice survives a future change of defaults.
  • Merged latest main.

Preview of Settings page

2026-07-16_21-01

@lidel lidel removed the status/blocked Unable to be worked further until needs are met label Jul 16, 2026
@lidel
lidel marked this pull request as ready for review July 16, 2026 19:12
@lidel
lidel merged commit bbd8a31 into main Jul 16, 2026
13 checks passed
@lidel
lidel deleted the feat/share-modal-local-gateway-url branch July 16, 2026 19:16
ipfs-gui-bot pushed a commit that referenced this pull request Jul 16, 2026
## [4.13.0](v4.12.0...v4.13.0) (2026-07-16)

 CID `bafybeiciqeyipumpmhxzlxnbqdbbv6u5uij4hy4wax64dmj7kvrhusiq6y`

 ---

### Features

* choose share link type, add native uris ([#2482](#2482)) ([bbd8a31](bbd8a31)), closes [#2486](#2486)
* **config:** add Local Gateway URL for reverse proxy and Docker ([#2486](#2486)) ([6a4acab](6a4acab)), closes [#2458](#2458) [#2383](#2383)

### Bug Fixes

* **files:** unpin option missing in batch delete ([#2488](#2488)) ([d87d88b](d87d88b)), closes [ipfs/ipfs-desktop#3134](https://github.com/ipfs/ipfs-desktop/issues/3134)
* **ipns:** surface publish errors to user ([#2493](#2493)) ([5cdb301](5cdb301)), closes [#2492](#2492)

### Trivial Changes

* pull transifex translations ([#2483](#2483)) ([9037406](9037406))
* pull transifex translations ([#2491](#2491)) ([2007bd8](2007bd8))
* pull transifex translations ([#2495](#2495)) ([78ce01a](78ce01a))
@ipfs-gui-bot

Copy link
Copy Markdown
Collaborator

🎉 This PR is included in version 4.13.0 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

lidel added a commit to ipfs/ipfs-companion that referenced this pull request Jul 17, 2026
Match the defaults ipfs/ipfs-webui#2482 shipped: fresh installs prefill
ipfs.io and dweb.link and copy dweb.link subdomain URLs, while clearing
the gateway URLs switches copied links to native ipfs:// and ipns://
URIs.

- options: defaults live in DEFAULT_* constants; a future flip to
  native-by-default changes those plus a migrateOptions entry
- ipfs-path: share links prefer the subdomain gateway and fall back to
  the path gateway, then native; roots longer than the 63-char DNS
  label limit no longer produce hostnames that cannot resolve
- options/store: clearing the last gateway URL no longer flips the
  share toggle off; the fallback is dynamic, so re-adding a URL
  restores public sharing
- recovery: resolve a native URI via the background once the node is
  online instead of navigating to ipfs://, which Chromium drops
- popup: show the local gateway address when no public one is set
- locales/en: describe the new behavior on the Preferences screen
lidel added a commit to ipfs/ipfs-companion that referenced this pull request Jul 17, 2026
* feat: make public gateways optional for sharing

Public gateway URLs are now empty by default, so "Copy Shareable
Link" and friends copy native ipfs:// and ipns:// URIs. A new opt-in
toggle restores public gateway URLs for sharing with people who do
not run IPFS.

- options: empty publicGatewayUrl/publicSubdomainGatewayUrl defaults
  plus usePublicGatewaysForShare (off, disabled until a public gateway
  URL is set)
- ipfs-path: resolveToNativeUri plus toggle-aware resolveToShareableUrl
  and resolveToPermalink (Copy Shareable and Snapshot Link);
  resolveToPublicUrl falls back to native on empty gateway
- public shareable links follow the "Use Subdomains" preference: on
  uses the subdomain gateway, off the path gateway, and whichever one
  is configured when only one is set
- native URIs use case-insensitive roots since browsers treat them as
  origins: base32 CIDv1 for ipfs://, base36 libp2p-key CIDv1 for
  ipns:// peer ids (DNSLink hostnames unchanged)
- empty gateways handled across state, request, dnslink, import and
  inspector: sameGateway/dropSlash are null-safe and browser-loading
  paths fall back to the local gateway
- recovery page: with no public gateway configured it shows the native
  ipfs:// address, drops the public-gateway wording, and offers to
  install a local IPFS node
- options UI: public gateway fields moved below the local gateway;
  path gateway renamed to make its shape explicit; both documented
  with link examples and links to the path/subdomain gateway specs

* fix: stop assuming a public gateway is set

Making public gateways optional left several consumers resolving to
native ipfs:// URIs they could not use, and routed offline failures to
dead ends. Degrade each consumer to a loadable URL or the recovery page.

- resolveToPublicUrl: use the subdomain gateway for content paths when
  only it is set, keep subdomain requests native rather than downgrade
  them to a path gateway (origin isolation), and repair the ipns://
  DNSLink protocol swap that URL.protocol assignment silently dropped
- recovery: send failed requests to the recovery page with the native
  URI when no loadable gateway remains, including failures at the
  configured gateway itself; only reopen on the local gateway when the
  node is online; limit HTTP recovery to 5xx
- preload: noop without a public gateway, otherwise pick a random
  configured one
- linkify: fall back to the local gateway so injected hrefs stay http(s)
- sharing: reset usePublicGatewaysForShare when both gateway URLs are
  cleared; share helpers no longer re-parse an already-decoded path
- sameGateway: match on a label boundary so nondefaultipfs.io is not
  treated as ipfs.io

* fix: keep sharing via public gateways by default

Match the defaults ipfs/ipfs-webui#2482 shipped: fresh installs prefill
ipfs.io and dweb.link and copy dweb.link subdomain URLs, while clearing
the gateway URLs switches copied links to native ipfs:// and ipns://
URIs.

- options: defaults live in DEFAULT_* constants; a future flip to
  native-by-default changes those plus a migrateOptions entry
- ipfs-path: share links prefer the subdomain gateway and fall back to
  the path gateway, then native; roots longer than the 63-char DNS
  label limit no longer produce hostnames that cannot resolve
- options/store: clearing the last gateway URL no longer flips the
  share toggle off; the fallback is dynamic, so re-adding a URL
  restores public sharing
- recovery: resolve a native URI via the background once the node is
  online instead of navigating to ipfs://, which Chromium drops
- popup: show the local gateway address when no public one is set
- locales/en: describe the new behavior on the Preferences screen

* chore: tidy copy on the preferences screen

- rename lingering "custom gateway" mentions to "local gateway"
- fix grammar in the automatic mode descriptions and a missing space
  in the notifications one

* fix: explain kubo rpc in the ipfs node section

The node type select had a single option, so it asked users to choose
nothing. Hide it while POSSIBLE_NODE_TYPES has one entry and instead
explain what the Kubo RPC API is, with links to install Kubo or IPFS
Desktop and to the RPC docs.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants